
void detachFromTerminal(int doChdir) {
  if(doChdir) {
    int rc = chdir("/");
    if(rc != 0) traceEvent(TRACE_ERROR, "Error while moving to / directory");
  }

  setsid();  /* detach from the terminal */

  fclose(stdin);
  fclose(stdout);
  /* fclose(stderr); */

  /*
   * clear any inherited file mode creation mask
   */
  umask (0);

  /*
   * Use line buffered stdout
   */
  /* setlinebuf (stdout); */
  setvbuf(stdout, (char *)NULL, _IOLBF, 0);
}

/* ************************************ */

void daemonize(void) {
  int childpid;

  signal(SIGHUP, SIG_IGN);
  signal(SIGCHLD, SIG_IGN);
  signal(SIGQUIT, SIG_IGN);

  if((childpid = fork()) < 0)
    traceEvent(TRACE_ERROR, "INIT: Occurred while daemonizing (errno=%d)", errno);
  else {
#ifdef DEBUG
    traceEvent(TRACE_INFO, "DEBUG: after fork() in %s (%d)",
	       childpid ? "parent" : "child", childpid);
#endif
    if(!childpid) { /* child */
      traceEvent(TRACE_INFO, "INIT: Bye bye: I'm becoming a daemon...");
      detachFromTerminal(1);
    } else { /* father */
      traceEvent(TRACE_INFO, "INIT: Parent process is exiting (this is normal)");
      exit(0);
    }
  }
}


/* ****************************************************** */

void setThreadAffinity(u_int core_id) {
#ifdef HAVE_PTHREAD_SET_AFFINITY
  if((getNumCores() > 1) && (readOnlyGlobals.numProcessThreads > 1)) {
    /* Bind this thread to a specific core */
    cpu_set_t cpuset;
    int rc;

    CPU_ZERO(&cpuset);
    CPU_SET(core_id, &cpuset);

    if((rc = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)) != 0)
      traceEvent(TRACE_ERROR, "Error while binding to core %ld: errno=%i\n",
		 core_id, rc);
    else {
      traceEvent(TRACE_INFO, "Bound thread to core %lu/%u\n", core_id, getNumCores());
    }
  }
#endif
}

/* ****************************************************** */
u_short getNumCores(void) {
#ifdef linux
  return(sysconf(_SC_NPROCESSORS_CONF));
#else
  return(ACT_NUM_PCAP_THREADS);
#endif
}

/* *********************************************** */

void initAtomic(atomic_u_int32_t *a) {
  a->value = 0;
#ifndef HAVE_BUILTIN_ATOMIC
  pthread_rwlock_init(&a->lock, NULL);
#endif
}

/* *********************************************** */

u_int32_t incAtomic(atomic_u_int32_t *a, u_int32_t value) {
#ifndef HAVE_BUILTIN_ATOMIC
  pthread_rwlock_wrlock(&a->lock);
  a->value += value;
  pthread_rwlock_unlock(&a->lock);
#else
  return((u_int32_t)__sync_add_and_fetch(&a->value, value));
#endif
}

/* *********************************************** */

u_int32_t decAtomic(atomic_u_int32_t *a, u_int32_t value) {
#ifndef HAVE_BUILTIN_ATOMIC
  pthread_rwlock_wrlock(&a->lock);
  a->value -= value;
  pthread_rwlock_unlock(&a->lock);
#else
  return((u_int32_t)__sync_sub_and_fetch(&a->value, value));
#endif
}

/* *********************************************** */

u_int32_t getAtomic(atomic_u_int32_t *a) {
  return(a->value);
}

/* *********************************************** */
